home *** CD-ROM | disk | FTP | other *** search
/ HamCall (October 1991) / HamCall (Whitehall Publishing)(1991).bin / prgming / ada / sortarry.ada < prev    next >
Text File  |  1987-10-19  |  62KB  |  1,587 lines

  1.  
  2. -------- SIMTEL20 Ada Software Repository Prologue ------------
  3. --                                                           -*
  4. -- Unit name    : generic package Sort_Utilities
  5. -- Version      : 1.3 (FRAY297)
  6. -- Author       : Geoffrey O. Mendal
  7. --              : Stanford University
  8. --              : Computer Systems Laboratory, ERL 456
  9. --              : Stanford, CA  94305
  10. --              : (415) 723-1414 or 723-1175
  11. -- DDN Address  : Mendal@SIERRA.STANFORD.EDU
  12. -- Copyright    : (c) 1985, 1986, 1987 Geoffrey O. Mendal
  13. -- Date created : Mon 11 Nov 85
  14. -- Release date : Sun 25 Dec 85
  15. -- Last update  : MENDAL Fri 29 May 87
  16. -- Machine/System Compiled/Run on : DG MV10000, ROLM ADE
  17. --                                  VAX 11/780, DEC ACS
  18. --                                  RATIONAL R1000
  19. --                                  SEQUENT B21000, VERDIX VADS
  20. --                                  SUN/3, VERDIX VADS
  21. -- Dependent Units : package SYSTEM
  22. --                                                           -*
  23. ---------------------------------------------------------------
  24. --                                                           -*
  25. -- Keywords     :  SORT
  26. ----------------:  SORT UTILITIES
  27. --
  28. -- Abstract     :  This generic package contains several
  29. ----------------:  array sorting routines.
  30. --                                                           -*
  31. ------------------ Revision history ---------------------------
  32. --                                                           -*
  33. -- DATE         VERSION              AUTHOR     HISTORY
  34. -- 12/29/85     1.0 (MOOV115)     Mendal     Initial Release
  35. -- 04/11/86     1.1 (FRPR116)     Mendal     ANNA formal comments
  36. -- 12/07/86     1.2 (SUEC076)     Mendal     more ANNA annotations
  37. -- 05/29/87     1.3 (FRAY297)     Mendal     annotation changes
  38. --                                                           -*
  39. ------------------ Distribution and Copyright -----------------
  40. --                                                           -*
  41. -- This prologue must be included in all copies of this software.
  42. --
  43. -- This software is copyright by the author.
  44. --
  45. -- This software is released to the Ada community.
  46. -- This software is released to the Public Domain (note:
  47. --   software released to the Public Domain is not subject
  48. --   to copyright protection).
  49. -- Restrictions on use or distribution:  NONE
  50. --                                                           -*
  51. ------------------ Disclaimer ---------------------------------
  52. --                                                           -*
  53. -- This software and its documentation are provided "AS IS" and
  54. -- without any expressed or implied warranties whatsoever.
  55. -- No warranties as to performance, merchantability, or fitness
  56. -- for a particular purpose exist.
  57. --
  58. -- Because of the diversity of conditions and hardware under
  59. -- which this software may be used, no warranty of fitness for
  60. -- a particular purpose is offered.  The user is advised to
  61. -- test the software thoroughly before relying on it.  The user
  62. -- must assume the entire risk and liability of using this
  63. -- software.
  64. --
  65. -- In no event shall any person or organization of people be
  66. -- held responsible for any direct, indirect, consequential
  67. -- or inconsequential damages or lost profits.
  68. --                                                           -*
  69. -------------------END-PROLOGUE--------------------------------
  70.  
  71. -- Sort_Utilities is a generic sorting package. The Sort subprograms
  72. -- will sort a one dimensional array of any component type that supports
  73. -- assignment, equality, and inequality (private types) indexed by
  74. -- discrete type components. The default linear order is ascending order
  75. -- but may be overridden by the user. The default sort algorithm,
  76. -- Quicksort (non-recursive), may also be overridden.
  77.  
  78. -- Note that the component type can be a record type. The Sort subprograms
  79. -- are not restricted to simple data types. If records are to be sorted,
  80. -- then the formal generic subprogram parameter "<" must be
  81. -- specified with by a linear order, e.g., a function provided
  82. -- as an actual generic subprogram parameter at instantiation.
  83.  
  84. -- Note that the component type can be an access type (which can
  85. -- point to other objects, improving sort efficiency). If access types
  86. -- are to be sorted, then the formal generic subprogram parameter "<"
  87. -- must be specified by a linear order (see example #3 below).
  88. -- Since access types can be sorted, the Sort routine below can be
  89. -- used to sort limited types and unconstrained types (designated by
  90. -- an access type).
  91.  
  92. -- For data in which equality does not truly apply (i.e., real types)
  93. -- one can use the Equal function to specify an equality operation.
  94. -- Hence, one can decide that two numbers are "close enough" to be
  95. -- equal (see example #4 below).
  96.  
  97. -- The number of comparisons and exchanges made to sort the array
  98. -- can be returned. These numbers should give some indication on how
  99. -- much work was actually performed by the sorting algorithms. These
  100. -- numbers can also be used to compare the relative efficiency
  101. -- of the sorting algorithms.
  102.  
  103. -- This package can be used to sort data on external devices. The user
  104. -- should use this package to sort a subset of the external data, then
  105. -- use a merge operation on all sorted subsets. For example, if the
  106. -- system can only hold 1000 components in RAM, but you need to sort
  107. -- 3000 components, bring in components #1-1000 and sort them using this
  108. -- routine, and then write them to a file. Next do the same with
  109. -- components #1001-2000, and finally with components #2001-3000. Now
  110. -- merge the three sorted files using a merge package.
  111.  
  112. -- One of the Sort subprograms is a function which can be used to sort
  113. -- an array and test it against another in an inline expression. This
  114. -- can be useful when comparing the contents of two arrays which may be
  115. -- equal, but not at the identical indices. This will be most useful for
  116. -- comparing the equality of sets implemented as arrays (see example #5
  117. -- below).
  118.  
  119. -- Other Sort subprograms allow the user to maintain the original state
  120. -- of the array by returning a new array that is sorted. These subprograms
  121. -- will be useful in cases where sorting is required, but the original
  122. -- (unsorted) data must be preserved.
  123.  
  124. -- This package has been formally annotated using the ANNA specification
  125. -- language. For more information, contact the author. Also, the
  126. -- design of this package has been documented in the IEEE Computer
  127. -- Society Second International Conference on Ada Applications and
  128. -- Environments proceedings. Contact the IEEE or the author for a copy
  129. -- of the paper. This paper is forthcoming in a special issue of IEEE
  130. -- Software also.
  131.  
  132. with SYSTEM;  -- predefined package SYSTEM
  133.  
  134. generic
  135.   type Component_Type is private;  -- type of the data components
  136.   type Index_Type     is (<>);     -- type of array index
  137.  
  138.   -- The following generic formal type is required due to Ada's
  139.   -- strong typing requirements. The SORT subprograms cannot handle
  140.   -- anonymous array types. This type will match any unconstrained
  141.   -- array type definition (so that array slices can be sorted
  142.   -- too -- see example #3 below).
  143.  
  144.   type Array_Type is array (Index_Type range <>) of Component_Type;
  145.  
  146.   -- The following formal subprogram parameter defaults to the
  147.   -- predefined "<" operator which will sort one-dimensional
  148.   -- arrays of Component_Type in ascending order (by default).
  149.   -- If composite or access types are to be sorted, a selector
  150.   -- function must be specified.
  151.  
  152.   with function "<" (Left,Right : in Component_Type) return BOOLEAN is <>;
  153.  
  154.   -- The following formal subprogram parameter defaults to the predefined
  155.   -- "=" operator. If user-defined equality is desired, one can write
  156.   -- an equality function and specify it here.
  157.  
  158.   with function Equal (Left,Right : in Component_Type) return BOOLEAN is "=";
  159.  
  160.   -- The annotations below formally specify assumptions about the
  161.   -- generic formals above that must be satisfied in order to perform
  162.   -- correct sorting.
  163.  
  164.   --| for all X, Y, Z : Component_Type =>
  165.   --|   (not (X < X)) and
  166.   --|   (Equal (X, Y) xor (X < Y) xor (Y < X)) and
  167.   --|   ((X < Y) and (Y < Z) -> (X < Z)) and
  168.  
  169.   --|   Equal (X, X) and
  170.   --|   (Equal (X, Y) -> Equal (Y, X)) and
  171.   --|   (Equal (X, Y) and Equal (Y, Z) -> Equal (X, Z)) and
  172.   --|   (Equal (X, Y) and (X < Z) -> (Y < Z)) and
  173.   --|   (Equal (X, Y) and (Z < X) -> (Z < Y));
  174. package Sort_Utilities is
  175.   function Version return STRING;  -- Returns the version number.
  176.  
  177.   -- Users can specify the type of sorting algorithm they want by
  178.   -- specifying an enumeration literal from the type below. The default
  179.   -- algorithm, Quicksort (non-recursive), generally performs best.
  180.  
  181.   -- One note about stability of the algorithms: only the Bubble Sorts
  182.   -- and Insertion Sort are stable algorithms. Thus, they are the
  183.   -- only algorithms that preserve the ordering of equal components
  184.   -- without use of a selector function. In all cases, a selector
  185.   -- function may be specified to introduce stability into the
  186.   -- sorting algorithms (see example #3 below).
  187.  
  188.   type Sort_Algorithm_Type is (Quicksort, Recursive_Quicksort, Bsort,
  189.     Bubble_Sort, Bubble_Sort_with_Quick_Exit, Selection_Sort, Heapsort,
  190.     Insertion_Sort, Merge_Sort);
  191.     
  192.   -- Quicksort:   O(NlogN). Is most efficient when used with large, unsorted
  193.   --              arrays. Uses an explicit stack to maintain state and
  194.   --              partitions. Instable. This is the default algorithm.
  195.   -- Recursive_Quicksort:  O(NlogN). Is most efficient when used with large,
  196.   --              unsorted arrays. Recursive nature may introduce significant
  197.   --              memory overhead for very large arrays. Instable.
  198.   -- Bsort:       O(NlogN). Is most efficient when used with large arrays
  199.   --              that are already sorted, partially sorted, or sorted in
  200.   --              reverse. Recursive. Instable.
  201.   -- Bubble_Sort: O(N**2). Is most efficient when used with small
  202.   --              arrays that are almost already sorted. Non-recursive.
  203.   --              Brute force. Low memory requirements. Stable.
  204.   -- Bubble_Sort_with_Quick_Exit: O(N**2). Is most efficient when
  205.   --              used with small arrays that are almost already sorted.
  206.   --              Non-recursive. Same as bubble sort above except brute
  207.   --              force is limited. Stable.
  208.   -- Selection_Sort: O(N**2). Is most efficient when used with
  209.   --              small arrays in which the Component_Type is a
  210.   --              record type. Non-recursive. Brute force. Instable.
  211.   -- Heapsort:    O(NlogN). Is most efficient when used with
  212.   --              large, unsorted arrays. Non-recursive. Very low
  213.   --              memory requirements. Instable.
  214.   -- Insertion_Sort: O(N**2). Is most efficient when used with
  215.   --              small arrays that are almost already sorted. Non-
  216.   --              recursive. Brute force. Stable.
  217.   -- Merge_Sort:  O(NlogN). Is most efficient when used with medium-large
  218.   --              arrays. Non-recursive. Instable. Uses an auxiliary array
  219.   --              to perform merging.
  220.  
  221.   -- The following type declaration should be used to specify the
  222.   -- instrumentation analysis results that can be returned by the Sort
  223.   -- subprograms below. -1 is only returned if an overflow in calculations
  224.   -- has occurred. The Sort subprograms will still sort the array if an
  225.   -- overflow in instrumentation analysis data calculations
  226.   -- occurs.
  227.  
  228.   type Performance_Instrumentation_Type is range -1 .. SYSTEM.MAX_INT;
  229.  
  230.   -- The following exception is raised during execution of the Sort
  231.   -- subprograms which take two arrays as parameters.  These two arrays
  232.   -- must be of the same length.
  233.  
  234.   Sort_Arrays_Length_Mismatch : exception;
  235.  
  236.   -- The following virtual functions define the semantics of sorting.
  237.   -- The use of Index_Type'SUCC and Index_Type'PRED might raise
  238.   -- CONSTRAINT_ERROR on boundary limits, and need to be enhanced
  239.   -- in these cases.  (An annotation that raises an exception during
  240.   -- its evaluation is not consistent with the specification.)
  241.  
  242.   --: function Ordered (A : in Array_Type) return BOOLEAN;
  243.   --|   where return (A'LENGTH <= 1) or else
  244.   --|           (((A (A'FIRST) < A (Index_Type'SUCC (A'FIRST))) or
  245.   --|             (Equal (A (A'FIRST), A (Index_Type'SUCC (A'FIRST))))) and
  246.   --|            Ordered (A (Index_Type'SUCC (A'FIRST) .. A'LAST)));
  247.  
  248.   --: function Permutation (A, B : in Array_Type) return BOOLEAN;
  249.   --|   where A'LENGTH = B'LENGTH,
  250.   --|         Ordered (B),
  251.   --|         return (A'LENGTH = 0) or else
  252.   --|           (exist I : B'RANGE =>
  253.   --|            Equal (A (A'FIRST), B (I)) and
  254.   --|            Permutation (A (Index_Type'SUCC (A'FIRST) .. A'LAST),
  255.   --|              B (B'FIRST .. Index_Type'PRED (I)) &
  256.   --|              B (Index_Type'SUCC (I) .. B'LAST)));
  257.  
  258.   -- The following procedure will sort a one dimensional array of
  259.   -- components. It can sort in ascending/descending order or any
  260.   -- user-defined order. It can sort components of any type that
  261.   -- support equality, inequality, and assignment (private types).
  262.   -- The array indices can be of any discrete type. The number of
  263.   -- comparisons and exchanges can also be returned.
  264.  
  265.   procedure Sort (
  266.     Sort_Array             : in out Array_Type;
  267.     Number_of_Comparisons,
  268.     Number_of_Exchanges    :    out Performance_Instrumentation_Type;
  269.     Sort_Algorithm         : in     Sort_Algorithm_Type := Quicksort);
  270.     --| where out Ordered (Sort_Array),
  271.     --|       out Permutation (in Sort_Array, Sort_Array),
  272.     --|       out Number_of_Comparisons'DEFINED,
  273.     --|       out Number_of_Exchanges'DEFINED,
  274.     --|       raise Sort_Arrays_Length_Mismatch => FALSE;
  275.  
  276.   -- The following overloading of procedure Sort should be specified
  277.   -- when no instrumentation analysis data are required.
  278.  
  279.   procedure Sort (
  280.     Sort_Array     : in out Array_Type;
  281.     Sort_Algorithm : in     Sort_Algorithm_Type := Quicksort);
  282.     --| where out Ordered (Sort_Array),
  283.     --|       out Permutation (in Sort_Array, Sort_Array),
  284.     --|       raise Sort_Arrays_Length_Mismatch => FALSE;
  285.     
  286.   -- The following overloading of procedure Sort should be used when
  287.   -- the original data must be preserved and instrumentation analysis
  288.   -- results are required.
  289.   
  290.   procedure Sort (
  291.     Unsorted_Array         : in     Array_Type;
  292.     Sorted_Array           :    out Array_Type;
  293.     Number_of_Comparisons,
  294.     Number_of_Exchanges    :    out Performance_Instrumentation_Type;
  295.     Sort_Algorithm         : in     Sort_Algorithm_Type := Quicksort);
  296.     --| where out Ordered (Sorted_Array),
  297.     --|       out Permutation (Unsorted_Array, Sorted_Array),
  298.     --|       out Number_of_Comparisons'DEFINED,
  299.     --|       out Number_of_Exchanges'DEFINED,
  300.     --|       Unsorted_Array'LENGTH /= Sorted_Array'LENGTH =>
  301.     --|         raise Sort_Arrays_Length_Mismatch;
  302.     
  303.   -- The following overloading of procedure Sort should be used when
  304.   -- the original data must be preserved and no instrumentation analysis
  305.   -- results are required.
  306.   
  307.   procedure Sort (
  308.     Unsorted_Array : in     Array_Type;
  309.     Sorted_Array   :    out Array_Type;
  310.     Sort_Algorithm : in     Sort_Algorithm_Type := Quicksort);
  311.     --| where out Ordered (Sorted_Array),
  312.     --|       out Permutation (Unsorted_Array, Sorted_Array),
  313.     --|       Unsorted_Array'LENGTH /= Sorted_Array'LENGTH =>
  314.     --|         raise Sort_Arrays_Length_Mismatch;
  315.     
  316.   -- The following overloading of function Sort should be used when
  317.   -- sorting is required in an inline expression.
  318.   
  319.   function Sort (
  320.     Sort_Array     : in Array_Type;
  321.     Sort_Algorithm : in Sort_Algorithm_Type := Quicksort)
  322.     return Array_Type;
  323.     --| where return A : Array_Type =>
  324.     --|   Ordered (A) and Permutation (Sort_Array, A);
  325.     --| raise Sort_Arrays_Length_Mismatch => FALSE;
  326. end Sort_Utilities;
  327.  
  328. -- Example uses/instantiations:
  329. --   -- EXAMPLE #1: Sorting an array of CHARACTERs
  330. --   with Sort_Utilities;
  331. --   procedure Main is
  332. --     type My_Index_Type is (Sun,Mon,Tue,Wed,Thu,Fri,Sat);
  333. --     type My_Array_Type is array (My_Index_Type range <>) of CHARACTER;
  334. --     package Ascending_Sort is new Sort_Utilities (
  335. --       Component_Type => CHARACTER,
  336. --       Index_Type     => My_Index_Type,
  337. --       Array_Type     => My_Array_Type);
  338. --     package Descending_Sort is new Sort_Utilities (
  339. --       Component_Type => CHARACTER,
  340. --       Index_Type     => My_Index_Type,
  341. --       Array_Type     => My_Array_Type,
  342. --       "<"            => ">");
  343. --     My_Array               : My_Array_Type (Mon .. Fri);
  344. --     Number_of_Comparisons,
  345. --     Number_of_Exchanges,   : Descending_Sort.Performance_Instrumentation_Type;
  346. --   begin
  347. --     Ascending_Sort.Sort (My_Array);
  348. --     Descending_Sort.Sort (
  349. --       Sort_Array             => My_Array,
  350. --       Number_of_Comparisons  => Number_of_Comparisons,
  351. --       Number_of_Exchanges    => Number_of_Exchanges,
  352. --       Sort_Algorithm         => Descending_Sort.Bubble_Sort);
  353. --   end Main;
  354. --   -------------------------------------------------------------------
  355. --   -- EXAMPLE #2: Sorting an array of records based on a key field
  356. --   with Sort_Utilities;
  357. --   procedure Main is
  358. --     type My_Component_Type is
  359. --       record
  360. --         Field1 : INTEGER;
  361. --         Field2 : FLOAT;
  362. --         Field3 : CHARACTER;
  363. --       end record;
  364. --     subtype My_Index_Type is INTEGER range -10 .. 10;
  365. --     type My_Array_Type is array (My_Index_Type range <>) of My_Component_Type;
  366. --     My_Array : My_Array_Type (-10 .. 10);
  367. --     function Ascending_Order_on_Field1 (Left,Right : in My_Component_Type) return BOOLEAN is
  368. --     begin
  369. --       return Left.Field1 < Right.Field1;
  370. --     end Ascending_Order_on_Field1;
  371. --     function Descending_Order_on_Field3 (Left,Right : in My_Component_Type) return BOOLEAN is
  372. --     begin
  373. --       return Left.Field3 > Right.Field3;
  374. --     end Descending_Order_on_Field3;
  375. --     package Ascending_Sort_on_Field1 is new Sort_Utilities (
  376. --       Component_Type => My_Component_Type,
  377. --       Index_Type     => My_Index_Type,
  378. --       Array_Type     => My_Array_Type,
  379. --       "<"            => Ascending_Order_on_Field1);
  380. --     package Descending_Sort_on_Field3 is new Sort_Utilities (
  381. --       Component_Type => My_Component_Type,
  382. --       Index_Type     => My_Index_Type,
  383. --       Array_Type     => My_Array_Type,
  384. --       "<"            => Descending_Order_on_Field3);
  385. --     Ascending_Sort_on_Field1.Sort (My_Array);
  386. --     Descending_Sort_on_Field3.Sort (
  387. --       Sort_Array     => My_Array,
  388. --       Sort_Algorithm => Descending_Sort_on_Field3.Selection_Sort);
  389. --   end Main;
  390. --   -------------------------------------------------------------------
  391. --   EXAMPLE #3: Sorting an array slice of access types that designate
  392. --               records.
  393. --   with Sort_Utilities;
  394. --   procedure Main is
  395. --     type Taxpayer_Type is
  396. --       record
  397. --         Name        : STRING (1 .. 40);
  398. --         Age         : NATURAL;
  399. --         ID_Number   : POSITIVE;   -- social security number
  400. --       end record;
  401. --     type Taxpayer_Access_Type is access Taxpayer_Type;
  402. --     type My_Index_Type is range 1 .. 1_000_000;
  403. --     type My_Array_Type is array (My_Index_Type range <>) of Taxpayer_Access_Type;
  404. --     My_Array : My_Array_Type (1 .. 1_000_000);
  405. --     function Ascending_Taxpayers (Left,Right : in Taxpayer_Access_Type) return BOOLEAN is
  406. --     begin
  407. --       return (Left.Name < Right.Name) or
  408. --              ((Left.Name = Right.Name) and (Left.ID_Number < Right.ID_Number));
  409. --     end Ascending_Taxpayers;
  410. --     package Ascending_Taxpayer_Sort is new Sort_Utilities (
  411. --       Taxpayer_Access_Type,My_Index_Type,My_Array_Type,Ascending_Taxpayers);
  412. --     Ascending_Taxpayer_Sort.Sort (My_Array(100..1_000));
  413. --   end Main;
  414. --   ---------------------------------------------------------------------------
  415. --   EXAMPLE #4: Sorting an array of floating point numbers using a
  416. --               constrained array subtype
  417. --   with Sort_Utilities;
  418. --   procedure Main is
  419. --     type My_Array_Type is array (POSITIVE range <>) of FLOAT;
  420. --     subtype My_Array_Subtype is My_Array_Type (1 .. 10);
  421. --     My_Array : My_Array_Subtype;
  422. --     function My_Equality (L, R : in FLOAT) is
  423. --     begin
  424. --       . . .  -- check for "close enough" on equality
  425. --       return <some BOOLEAN expression>;
  426. --     end My_Equality;
  427. --     package My_Sort_Utilities is new Sort_Utilities (FLOAT,POSITIVE,My_Array_Type,
  428. --       My_Equality);
  429. --   begin
  430. --     My_Sort_Utilities.Sort (My_Array);
  431. --   end Main;
  432. --   ---------------------------------------------------------------------------
  433. --   EXAMPLE #5: Sorting in an inline expression
  434. --   with Sort_Utilities;
  435. --   procedure Main is
  436. --     type Set_Type is array (POSITIVE range <>) of CHARACTER;
  437. --     Set1,
  438. --     Set2 : Set_Type (1 .. 10);
  439. --     package My_Sort_Utilities is new Sort_Utilities (CHARACTER,POSITIVE,Set_Type);
  440. --   begin
  441. --     if My_Sort_Utilities.Sort (Set1) = My_Sort_Utilities.Sort (Set2) then
  442. --       . . .
  443. --     end if;
  444. --   end Main;
  445.  
  446. package body Sort_Utilities is
  447.   Version_Number : constant STRING := "1.3 (FRAY297)";
  448.  
  449. --: function Ordered (A : in Array_Type) return BOOLEAN is
  450. --: begin
  451. --:   for I in A'FIRST .. Index_Type'PRED (A'LAST) loop
  452. --:     if A (Index_Type'SUCC (I)) < A (I) then
  453. --:       return FALSE;
  454. --:     end if;
  455. --:   end loop;
  456. --:   return TRUE;
  457. --: end Ordered;
  458.  
  459. --: function Permutation (A, B : in Array_Type) return BOOLEAN is
  460. --:   type Mark_Array_Type is array (A'RANGE) of BOOLEAN;
  461. --:   Mark       : Mark_Array_Type := (others => FALSE);
  462. --:   Mark_Pos   : Index_Type;
  463. --:   Not_Marked : BOOLEAN;
  464. --: begin
  465. --:   for I in A'RANGE loop
  466. --:     Not_Marked := TRUE;
  467. --:     for J in B'RANGE loop
  468. --:       if Equal (A (I), B (J)) and not Mark (J) then
  469. --:         Mark_Pos := J;
  470. --:         exit;
  471. --:       end if;
  472. --:     end loop;
  473. --:     if Not_Marked then
  474. --:       return FALSE;
  475. --:     else
  476. --:       Mark (Mark_Pos) := TRUE;
  477. --:     end if;
  478. --:   end loop;
  479. --:   return Mark = (others => TRUE);
  480. --: end Permutation;
  481.  
  482.   function Version return STRING is
  483.   begin
  484.     return Version_Number;
  485.   end Version;
  486.  
  487.   -- The following subprograms are utilities for the sorting
  488.   -- procedures that follow them.
  489.  
  490.   procedure Update_Performance_Instrumentation (
  491.     Instrumentation_Count : in out Performance_Instrumentation_Type) is
  492.   begin
  493.     -- Bump the counter unless an overflow has occurred.
  494.  
  495.     if Instrumentation_Count /= Performance_Instrumentation_Type'FIRST then
  496.       if Instrumentation_Count /= Performance_Instrumentation_Type'LAST then
  497.         Instrumentation_Count := Instrumentation_Count + 1;
  498.       else
  499.         Instrumentation_Count := Performance_Instrumentation_Type'FIRST;
  500.       end if;
  501.     end if;
  502.   end Update_Performance_Instrumentation;
  503.  
  504.   procedure Exchange_Array_Components (
  505.     Sort_Array          : in out Array_Type;
  506.     Number_of_Exchanges : in out Performance_Instrumentation_Type) is
  507.  
  508.     Temporary_Component : constant Component_Type :=
  509.       Sort_Array (Sort_Array'FIRST);
  510.   begin
  511.     Sort_Array (Sort_Array'FIRST) := Sort_Array (Sort_Array'LAST);
  512.     Sort_Array (Sort_Array'LAST) := Temporary_Component;
  513.  
  514.     Update_Performance_Instrumentation (Number_of_Exchanges);
  515.   end Exchange_Array_Components;
  516.  
  517.   -- Procedure Quicksort is the default sort algorithm used. It is
  518.   -- a non-recursive method of sorting by constantly partitioning the
  519.   -- array in half and sorting only that half. This algorithm is
  520.   -- O(NlogN) and is instable.
  521.  
  522.   procedure Quicksort (
  523.     Sort_Array             : in out Array_Type;
  524.     Number_of_Comparisons,
  525.     Number_of_Exchanges    :    out Performance_Instrumentation_Type) is
  526.  
  527.     type Sort_Array_Index_Save_Type is
  528.       record
  529.         Left,
  530.         Right : Index_Type;
  531.       end record;
  532.  
  533.     subtype Stack_Index_Type is NATURAL range 0 .. Sort_Array'LENGTH;
  534.  
  535.     type Stack_Array_Type is array (Stack_Index_Type) of
  536.       Sort_Array_Index_Save_Type;
  537.  
  538.     Local_Comparisons,
  539.     Local_Exchanges    : Performance_Instrumentation_Type := 0;
  540.     I, J, L, R          : Index_Type;
  541.     Temporary_Component : Component_Type;
  542.     Stack_Pointer       : Stack_Index_Type;
  543.     Stack_Array         : Stack_Array_Type;
  544.   begin
  545.     if Sort_Array'FIRST < Sort_Array'LAST then
  546.       Stack_Pointer := 1;
  547.       Stack_Array (1).Left  := Sort_Array'FIRST;
  548.       Stack_Array (1).Right := Sort_Array'LAST;
  549.  
  550.       loop  -- Take top request from stack.
  551.         L := Stack_Array (Stack_Pointer).Left;
  552.         R := Stack_Array (Stack_Pointer).Right;
  553.         Stack_Pointer := Stack_Pointer - 1;
  554.  
  555.         loop  -- Split Sort_Array (Sort_Array'FIRST) .. Sort_Array (R).
  556.           I := L;
  557.           J := R;
  558.           Temporary_Component := Sort_Array (Index_Type'VAL (
  559.             ((Index_Type'POS (L) + Index_Type'POS (R)) / 2)));
  560.  
  561.           loop
  562.             loop
  563.               Update_Performance_Instrumentation (Local_Comparisons);
  564.  
  565.               exit when (not (Sort_Array (I) < Temporary_Component)) or
  566.                         (I = Sort_Array'LAST);
  567.  
  568.               I := Index_Type'SUCC (I);
  569.             end loop;
  570.  
  571.             loop
  572.               Update_Performance_Instrumentation (Local_Comparisons);
  573.  
  574.               exit when (not (Temporary_Component < Sort_Array (J))) or
  575.                         (J = Sort_Array'FIRST);
  576.  
  577.               J := Index_Type'PRED (J);
  578.             end loop;
  579.  
  580.             if I <= J then
  581.               if I /= J then
  582.                 Exchange_Array_Components (Sort_Array (I .. J),Local_Exchanges);
  583.               end if;
  584.  
  585.               if I /= Sort_Array'LAST then
  586.                 I := Index_Type'SUCC (I);
  587.               end if;
  588.  
  589.               if J /= Sort_Array'FIRST then
  590.                 J := Index_Type'PRED (J);
  591.               end if;
  592.             end if;
  593.  
  594.             exit when I > J;
  595.           end loop;
  596.  
  597.           if (Index_Type'POS (J) - Index_Type'POS (L)) <
  598.              (Index_Type'POS (R) - Index_Type'POS (I)) then
  599.             if I < R then
  600.               -- Stack request for sorting right partition.
  601.  
  602.               Stack_Pointer := Stack_Pointer + 1;
  603.               Stack_Array (Stack_Pointer).Left  := I;
  604.               Stack_Array (Stack_Pointer).Right := R;
  605.             end if;
  606.  
  607.             R := J;  -- Continue sorting left partition.
  608.           else
  609.             if L < J then
  610.               -- Stack request for sorting left partition.
  611.  
  612.               Stack_Pointer := Stack_Pointer + 1;
  613.               Stack_Array (Stack_Pointer).Left  := L;
  614.               Stack_Array (Stack_Pointer).Right := J;
  615.             end if;
  616.  
  617.             L := I;  -- Continue sorting right partition.
  618.           end if;
  619.  
  620.           exit when L >= R;
  621.         end loop;
  622.  
  623.         exit when Stack_Pointer = 0;
  624.       end loop;
  625.     end if;
  626.  
  627.     Number_of_Comparisons := Local_Comparisons;
  628.     Number_of_Exchanges   := Local_Exchanges;
  629.   end Quicksort;
  630.  
  631.   -- The following procedure houses a Quicksort that is identical to
  632.   -- the one above, except that recursion manages the state and paritions
  633.   -- instead of an explicit stack.
  634.  
  635.   procedure Recursive_Quicksort (
  636.     Sort_Array             : in out Array_Type;
  637.     Number_of_Comparisons,
  638.     Number_of_Exchanges    :    out Performance_Instrumentation_Type) is
  639.  
  640.     Local_Comparisons,
  641.     Local_Exchanges    : Performance_Instrumentation_Type := 0;
  642.  
  643.     -- The recursive nature of the sorting algorithm is found in
  644.     -- the procedure below.
  645.  
  646.     procedure Recursive_Quick (Sort_Array : in out Array_Type) is
  647.       I : Index_Type := Sort_Array'FIRST;
  648.       J : Index_Type := Sort_Array'LAST;
  649.  
  650.       -- The partitioning of the array in half is found in the
  651.       -- procedure below. It is this procedure that really sorts
  652.       -- the array by making the necessary exchanges.
  653.  
  654.       -- This algorithm DEPENDS on the fact that there are two or
  655.       -- more array components. Singleton or null arrays are special cases
  656.       -- and should be handled by the outermost level of the
  657.       -- Quicksort algorithm.
  658.  
  659.       procedure Partition is
  660.         Sort_Array_Mid_Value : constant Component_Type :=
  661.           Sort_Array (Index_Type'VAL ((Index_Type'POS (I) + Index_Type'POS (J)) / 2));
  662.       begin
  663.         loop
  664.           while (Sort_Array (I) < Sort_Array_Mid_Value) and
  665.                 (I /= Sort_Array'LAST) loop
  666.             Update_Performance_Instrumentation (Local_Comparisons);
  667.  
  668.             I := Index_Type'SUCC (I);
  669.           end loop;
  670.  
  671.           while (Sort_Array_Mid_Value < Sort_Array (J)) and
  672.                 (J /= Sort_Array'FIRST) loop
  673.             Update_Performance_Instrumentation (Local_Comparisons);
  674.  
  675.             J := Index_Type'PRED (J);
  676.           end loop;
  677.  
  678.           if I <= J then
  679.             if I < J then
  680.               Exchange_Array_Components (Sort_Array (I .. J),Local_Exchanges);
  681.             end if;
  682.  
  683.             if I /= Sort_Array'LAST then
  684.               I := Index_Type'SUCC (I);
  685.             end if;
  686.  
  687.             if J /= Sort_Array'FIRST then
  688.               J := Index_Type'PRED (J);
  689.             end if;
  690.           end if;
  691.  
  692.           exit when (I > J) or
  693.                     ((I = Sort_Array'LAST) and (J = Sort_Array'FIRST));
  694.         end loop;
  695.       end Partition;
  696.     begin  -- Recursive_Quick
  697.       Partition;
  698.  
  699.       if Sort_Array'FIRST < J then
  700.         Recursive_Quick (Sort_Array (Sort_Array'FIRST .. J));
  701.       end if;
  702.  
  703.       if I < Sort_Array'LAST then
  704.         Recursive_Quick (Sort_Array (I .. Sort_Array'LAST));
  705.       end if;
  706.     end Recursive_Quick;
  707.   begin  -- Recursive_Quicksort
  708.     -- Handle the special cases of singleton and null arrays...
  709.     -- do nothing.
  710.  
  711.     if Sort_Array'FIRST < Sort_Array'LAST then
  712.       Recursive_Quick (Sort_Array);
  713.     end if;
  714.  
  715.     Number_of_Comparisons := Local_Comparisons;
  716.     Number_of_Exchanges   := Local_Exchanges;
  717.   end Recursive_Quicksort;
  718.  
  719.   -- A variation on Recursive_Quicksort is found in the procedure below. It
  720.   -- is good for sorting data that is already ordered, partially ordered,
  721.   -- or reverse ordered. The algorithm is O(NlogN) and instable. It is
  722.   -- a combination of Recursive_Quicksort and Bubble_Sort_with_Quick_Exit.
  723.  
  724.   procedure Bsort (
  725.     Sort_Array             : in out Array_Type;
  726.     Number_of_Comparisons,
  727.     Number_of_Exchanges    :    out Performance_Instrumentation_Type) is
  728.  
  729.     Local_Comparisons,
  730.     Local_Exchanges    : Performance_Instrumentation_Type := 0;
  731.  
  732.     -- The recursive nature of the algorithm is found in the procedure below.
  733.  
  734.     procedure Recursive_Bsort (
  735.       Low_Index,
  736.       High_Index    : in Index_Type;
  737.       Mid_Component : in Component_Type) is
  738.  
  739.       Flag, Left_Flag, Right_Flag : BOOLEAN;
  740.       I, J                        : Index_Type;
  741.       Size                        : NATURAL;
  742.  
  743.       -- Sort_Array (Low_Index .. High_Index) are the components to be
  744.       -- sorted, and Mid_Component is the value of the middle component.
  745.       -- I and J are used to partition the subfiles so that at any time
  746.       -- Sort_Array (I) < Mid_Component and (Mid_Component < Sort_Array (J)
  747.       -- or Mid_Component = Sort_Array (J)). Left_Flag is TRUE whenever
  748.       -- the left subfile is not in sorted order, and Right_Flag is
  749.       -- TRUE whenever the right subfile is not in sorted order. Flag is
  750.       -- FALSE when the partitioning processes are completed.
  751.     begin
  752.       if Low_Index < High_Index then
  753.         Left_Flag  := FALSE;
  754.         Right_Flag := FALSE;
  755.         I          := Low_Index;
  756.         J          := High_Index;
  757.         Flag       := TRUE;
  758.  
  759.         while Flag loop
  760.           loop
  761.             Update_Performance_Instrumentation (Local_Comparisons);
  762.  
  763.             exit when (Mid_Component < Sort_Array (I)) or
  764.                       Equal (Mid_Component,Sort_Array (I)) or (I = J);
  765.  
  766.             -- Build the left subfile ensuring that the rightmost component
  767.             -- is always the largest of the subfile.
  768.  
  769.             if I /= Low_Index then
  770.               Update_Performance_Instrumentation (Local_Comparisons);
  771.  
  772.               if Sort_Array (I) < Sort_Array (Index_Type'PRED (I)) then
  773.                 Exchange_Array_Components (
  774.                   Sort_Array (Index_Type'PRED (I) .. I),Local_Exchanges);
  775.  
  776.                 Left_Flag := TRUE;
  777.               end if;
  778.             end if;
  779.  
  780.             I := Index_Type'SUCC (I);
  781.           end loop;
  782.  
  783.           loop
  784.             Update_Performance_Instrumentation (Local_Comparisons);
  785.  
  786.             exit when (Sort_Array (J) < Mid_Component) or (I = J);
  787.  
  788.             -- Build the right subfile ensuring that the leftmost component
  789.             -- is always the smallest of the subfile.
  790.  
  791.             if J /= High_Index then
  792.               Update_Performance_Instrumentation (Local_Comparisons);
  793.  
  794.               if Sort_Array (Index_Type'SUCC (J)) < Sort_Array (J) then
  795.                 Exchange_Array_Components (
  796.                   Sort_Array (J .. Index_Type'SUCC (J)),Local_Exchanges);
  797.  
  798.                 Right_Flag := TRUE;
  799.               end if;
  800.             end if;
  801.  
  802.             J := Index_Type'PRED (J);
  803.           end loop;
  804.  
  805.           if I /= J then
  806.             -- Interchange Sort_Array (I) from the left subfile with
  807.             -- Sort_Array (J) from the right subfile.
  808.  
  809.             Exchange_Array_Components (Sort_Array (I .. J),Local_Exchanges);
  810.           else  -- I = J
  811.             -- Partitioning into left and right subfiles has been completed.
  812.  
  813.             Update_Performance_Instrumentation (Local_Comparisons);
  814.  
  815.             if (Mid_Component < Sort_Array (J)) or
  816.                Equal (Mid_Component,Sort_Array (J)) then
  817.               -- Check the right subfile to ensure the first component,
  818.               -- Sort_Array (J), is the smallest.
  819.  
  820.               if J /= Sort_Array'LAST then
  821.                 Update_Performance_Instrumentation (Local_Comparisons);
  822.  
  823.                 if Sort_Array (Index_Type'SUCC (J)) < Sort_Array (J) then
  824.                   Exchange_Array_Components (
  825.                     Sort_Array (J .. Index_Type'SUCC (J)),Local_Exchanges);
  826.  
  827.                   Right_Flag := TRUE;
  828.                 end if;
  829.               end if;
  830.             else
  831.               -- Check the left subfile to ensure the last component,
  832.               -- Sort_Array (Index_Type'PRED (I)), is the largest.
  833.  
  834.               if I /= Sort_Array'FIRST then
  835.                 Update_Performance_Instrumentation (Local_Comparisons);
  836.  
  837.                 if Sort_Array (I) < Sort_Array (Index_Type'PRED (I)) then
  838.                   Exchange_Array_Components (
  839.                     Sort_Array (Index_Type'PRED (I) .. I),Local_Exchanges);
  840.  
  841.                   Left_Flag := TRUE;
  842.                 end if;
  843.               end if;
  844.  
  845.               if I > Index_Type'SUCC (Sort_Array'FIRST) then
  846.                 Update_Performance_Instrumentation (Local_Comparisons);
  847.  
  848.                 if Sort_Array (Index_Type'PRED (I)) <
  849.                    Sort_Array (Index_Type'PRED (Index_Type'PRED (I))) then
  850.                   Exchange_Array_Components (
  851.                     Sort_Array (Index_Type'PRED (Index_Type'PRED (I)) ..
  852.                                 Index_Type'PRED (I)),Local_Exchanges);
  853.                 end if;
  854.               end if;
  855.             end if;
  856.  
  857.             Flag := FALSE;
  858.           end if;  -- end of "if I /= J"
  859.         end loop;  -- end of "while Flag loop"
  860.  
  861.         -- Process the left subfile.
  862.  
  863.         Size := Index_Type'POS (I) - Index_Type'POS (Low_Index);
  864.  
  865.         if Size > 2 then
  866.           -- Subfile must have at least three components to process and
  867.           -- not already sorted.
  868.  
  869.           if Left_Flag then
  870.             if Size = 3 then
  871.               -- Special case of 3 components; place Sort_Array (Low_Index)
  872.               -- and Sort_Array (Index_Type'SUCC (Low_Index)) in sorted order.
  873.  
  874.               Update_Performance_Instrumentation (Local_Comparisons);
  875.  
  876.               if Sort_Array (Index_Type'SUCC (Low_Index)) <
  877.                  Sort_Array (Low_Index) then
  878.                 Exchange_Array_Components (
  879.                   Sort_Array (Low_Index .. Index_Type'SUCC (Low_Index)),
  880.                     Local_Exchanges);
  881.               end if;
  882.             else
  883.               Recursive_Bsort (Low_Index,Index_Type'PRED (Index_Type'PRED (I)),
  884.                 Sort_Array (Index_Type'VAL (
  885.                            ((Index_Type'POS (Low_Index) + Index_Type'POS (I)
  886.                              - 2) / 2)
  887.                           )));
  888.             end if;
  889.           end if;
  890.         end if;
  891.  
  892.         -- Process the right subfile.
  893.  
  894.         Size := Index_Type'POS (High_Index) - Index_Type'POS (J) + 1;
  895.  
  896.         if Size > 2 then
  897.           -- Subfile must have at least 3 components to process and not
  898.           -- already sorted.
  899.  
  900.           if Right_Flag then
  901.             if Size = 3 then
  902.               -- Special case of 3 components; place
  903.               -- Sort_Array (Index_Type'SUCC (J)) and
  904.               -- Sort_Array (Index_Type'SUCC (Index_Type'SUCC (J))) in sorted
  905.               -- order.
  906.  
  907.               Update_Performance_Instrumentation (Local_Comparisons);
  908.  
  909.               if Sort_Array (Index_Type'SUCC (Index_Type'SUCC (J))) <
  910.                  Sort_Array (Index_Type'SUCC (J)) then
  911.                 Exchange_Array_Components (
  912.                   Sort_Array (Index_Type'SUCC (J) ..
  913.                               Index_Type'SUCC (Index_Type'SUCC (J))),
  914.                               Local_Exchanges);
  915.               end if;
  916.             else
  917.               Recursive_Bsort (Index_Type'SUCC (J),High_Index,
  918.                 Sort_Array (Index_Type'VAL (
  919.                            ((Index_Type'POS (J) + Index_Type'POS (High_Index)
  920.                              + 1) / 2)
  921.                           )));
  922.             end if;
  923.           end if;
  924.         end if;
  925.       end if;  -- end of "if M < N then"
  926.     end Recursive_Bsort;
  927.   begin  -- Bsort
  928.     -- Do not bother with singleton and null arrays.
  929.  
  930.     if Sort_Array'FIRST < Sort_Array'LAST then
  931.       Recursive_Bsort (Sort_Array'FIRST,Sort_Array'LAST,
  932.         Sort_Array (Index_Type'VAL (
  933.          ((Index_Type'POS (Sort_Array'FIRST) +
  934.            Index_Type'POS (Sort_Array'LAST)) / 2))));
  935.     end if;
  936.  
  937.     Number_of_Comparisons := Local_Comparisons;
  938.     Number_of_Exchanges   := Local_Exchanges;
  939.   end Bsort;
  940.  
  941.   -- A bubble sort algorithm is found in the procedure below. The
  942.   -- algorithm used is a standard bubble sort. This algorithm is
  943.   -- O(N**2) and is stable.
  944.  
  945.   procedure Bubble_Sort (
  946.     Sort_Array             : in out Array_Type;
  947.     Number_of_Comparisons,
  948.     Number_of_Exchanges    :    out Performance_Instrumentation_Type) is
  949.  
  950.     Local_Comparisons,
  951.     Local_Exchanges    : Performance_Instrumentation_Type := 0;
  952.   begin
  953.     -- Check for the singleton/null array cases... do nothing.
  954.  
  955.     if Sort_Array'FIRST < Sort_Array'LAST then
  956.       for I in Sort_Array'FIRST .. Index_Type'VAL (Index_Type'POS (Sort_Array'LAST) - 1) loop
  957.         for J in Sort_Array'FIRST ..
  958.                  Index_Type'VAL (
  959.                                  (Index_Type'POS (Sort_Array'LAST)  +
  960.                                   Index_Type'POS (Sort_Array'FIRST) - 1
  961.                                  ) -
  962.                                  Index_Type'POS (I)
  963.                                 ) loop
  964.           Update_Performance_Instrumentation (Local_Comparisons);
  965.  
  966.           if Sort_Array (Index_Type'SUCC (J)) < Sort_Array (J) then
  967.             Exchange_Array_Components (Sort_Array (J .. Index_Type'SUCC (J)),
  968.                                        Local_Exchanges);
  969.           end if;
  970.         end loop;
  971.       end loop;
  972.     end if;
  973.  
  974.     Number_of_Comparisons := Local_Comparisons;
  975.     Number_of_Exchanges   := Local_Exchanges;
  976.   end Bubble_Sort;
  977.  
  978.   -- A bubble sort algorithm is found in the procedure below. The
  979.   -- algorithm used is a standard bubble sort with a quick exit. The
  980.   -- quick exit is taken if the data just happens to be sorted
  981.   -- in the middle of the process. Thus, this algorithm may be faster
  982.   -- than O(N**2) for arrays that are already partially ordered.
  983.  
  984.   procedure Bubble_Sort_with_Quick_Exit (
  985.     Sort_Array             : in out Array_Type;
  986.     Number_of_Comparisons,
  987.     Number_of_Exchanges    :    out Performance_Instrumentation_Type) is
  988.  
  989.     Local_Comparisons,
  990.     Local_Exchanges    : Performance_Instrumentation_Type := 0;
  991.     Interchange_Made   : BOOLEAN;
  992.   begin
  993.     -- Check for the singleton/null array cases... do nothing.
  994.  
  995.     if Sort_Array'FIRST < Sort_Array'LAST then
  996.       for I in Sort_Array'FIRST .. Index_Type'VAL (
  997.                Index_Type'POS (Sort_Array'LAST) - 1) loop
  998.         Interchange_Made := FALSE;
  999.  
  1000.         for J in Sort_Array'FIRST ..
  1001.                  Index_Type'VAL (
  1002.                                  (Index_Type'POS (Sort_Array'LAST) +
  1003.                                   Index_Type'POS (Sort_Array'FIRST) - 1
  1004.                                  ) -
  1005.                                  Index_Type'POS (I)
  1006.                                 ) loop
  1007.           Update_Performance_Instrumentation (Local_Comparisons);
  1008.  
  1009.           if Sort_Array (Index_Type'SUCC (J)) < Sort_Array (J) then
  1010.             Interchange_Made := TRUE;
  1011.             Exchange_Array_Components (Sort_Array (J .. Index_Type'SUCC (J)),
  1012.                                        Local_Exchanges);
  1013.           end if;
  1014.         end loop;
  1015.  
  1016.         exit when not Interchange_Made;
  1017.       end loop;
  1018.     end if;
  1019.  
  1020.     Number_of_Comparisons := Local_Comparisons;
  1021.     Number_of_Exchanges   := Local_Exchanges;
  1022.   end Bubble_Sort_with_Quick_Exit;
  1023.  
  1024.   -- A straight selection sort follows below. It is O(N**2) and
  1025.   -- is instable.
  1026.  
  1027.   procedure Selection_Sort (
  1028.     Sort_Array             : in out Array_Type;
  1029.     Number_of_Comparisons,
  1030.     Number_of_Exchanges    :    out Performance_Instrumentation_Type) is
  1031.  
  1032.     Local_Comparisons,
  1033.     Local_Exchanges    : Performance_Instrumentation_Type := 0;
  1034.     Small              : Index_Type;
  1035.   begin
  1036.     -- Check for singelton/null array case... do nothing.
  1037.  
  1038.     if Sort_Array'FIRST < Sort_Array'LAST then
  1039.       for I in Sort_Array'FIRST .. Index_Type'PRED (Sort_Array'LAST) loop
  1040.         Small := I;
  1041.  
  1042.         for J in Index_Type'SUCC (I) .. Sort_Array'LAST loop
  1043.           Update_Performance_Instrumentation (Local_Comparisons);
  1044.  
  1045.           if Sort_Array (J) < Sort_Array (Small) then
  1046.             Small := J;
  1047.           end if;
  1048.         end loop;
  1049.  
  1050.         if I /= Small then
  1051.           Exchange_Array_Components (Sort_Array (I .. Small),Local_Exchanges);
  1052.         end if;
  1053.       end loop;
  1054.     end if;
  1055.  
  1056.     Number_of_Comparisons := Local_Comparisons;
  1057.     Number_of_Exchanges   := Local_Exchanges;
  1058.   end Selection_Sort;
  1059.  
  1060.   -- Heapsort follows below. It is O(NlogN) and is instable.
  1061.  
  1062.   procedure Heapsort (
  1063.     Sort_Array             : in out Array_Type;
  1064.     Number_of_Comparisons,
  1065.     Number_of_Exchanges    :    out Performance_Instrumentation_Type) is
  1066.  
  1067.     Local_Comparisons,
  1068.     Local_Exchanges     : Performance_Instrumentation_Type := 0;
  1069.     I,J                 : Index_Type;
  1070.     Temporary_Component : Component_Type;
  1071.   begin
  1072.     -- Check for special array cases: do nothing on singleton/null,
  1073.     -- must handle an array of 2 elements separate since the algorithm
  1074.     -- assumes that Sort_Array'LENGTH >= 3.
  1075.  
  1076.     if Sort_Array'LENGTH = 2 then
  1077.       Update_Performance_Instrumentation (Local_Comparisons);
  1078.  
  1079.       if Sort_Array (Sort_Array'LAST) < Sort_Array (Sort_Array'FIRST) then
  1080.         Exchange_Array_Components (Sort_Array,Local_Exchanges);
  1081.       end if;
  1082.     elsif Sort_Array'FIRST < Sort_Array'LAST then
  1083.       -- Create initial heap.
  1084.  
  1085.       for K in Index_Type'SUCC (Sort_Array'FIRST) .. Sort_Array'LAST loop
  1086.         -- Insert Sort_Array (K) into existing heap of size K-1.
  1087.  
  1088.         I := K;
  1089.         Temporary_Component := Sort_Array (K);
  1090.  
  1091.         -- The complex expression in assigning to J below is necessary
  1092.         -- due to the generic nature of the algorithm. This
  1093.         -- expression is used in other places below too.
  1094.  
  1095.         if Index_Type'POS (I) >= 0 then
  1096.           J := Index_Type'VAL ((Index_Type'POS (I) +
  1097.                Index_Type'POS (Sort_Array'FIRST) - 1) / 2);
  1098.         elsif ((Index_Type'POS (I) + Index_Type'POS (Sort_Array'FIRST) - 1)
  1099.                mod 2) = 0 then
  1100.           J := Index_Type'VAL ((Index_Type'POS (I) +
  1101.                Index_Type'POS (Sort_Array'FIRST) - 1) / 2);
  1102.         else
  1103.           J := Index_Type'VAL ((Index_Type'POS (I) +
  1104.                Index_Type'POS (Sort_Array'FIRST) - 2) / 2);
  1105.         end if;
  1106.  
  1107.         while J >= Sort_Array'FIRST loop
  1108.           Update_Performance_Instrumentation (Local_Comparisons);
  1109.  
  1110.           exit when (Temporary_Component < Sort_Array (J)) or
  1111.             Equal (Temporary_Component,Sort_Array (J));
  1112.  
  1113.           Update_Performance_Instrumentation (Local_Exchanges);
  1114.           Sort_Array (I) := Sort_Array (J);
  1115.           I := J;
  1116.  
  1117.           if Index_Type'POS (I) >= 0 then
  1118.             if (((Index_Type'POS (I) + Index_Type'POS (Sort_Array'FIRST) - 1) / 2) >=
  1119.                 Index_Type'POS (Sort_Array'FIRST)
  1120.                ) and
  1121.                (I /= Sort_Array'FIRST) then
  1122.               J := Index_Type'VAL (
  1123.                      (Index_Type'POS (I) + Index_Type'POS (Sort_Array'FIRST) - 1)
  1124.                      / 2);
  1125.             else
  1126.               exit;  -- Exit while loop.
  1127.             end if;
  1128.           elsif ((Index_Type'POS (I) + Index_Type'POS (Sort_Array'FIRST) - 1)
  1129.                  mod 2) = 0 then
  1130.              if (((Index_Type'POS (I) + Index_Type'POS (Sort_Array'FIRST) - 1) / 2) >=
  1131.                  Index_Type'POS (Sort_Array'FIRST)
  1132.                 ) and
  1133.                 (I /= Sort_Array'FIRST) then
  1134.                J := Index_Type'VAL (
  1135.                       (Index_Type'POS (I) + Index_Type'POS (Sort_Array'FIRST) - 1)
  1136.                       / 2);
  1137.              else
  1138.                exit;  -- Exit while loop.
  1139.              end if;
  1140.            elsif (((Index_Type'POS (I) + Index_Type'POS (Sort_Array'FIRST) - 1) / 2) >=
  1141.                   Index_Type'POS (Sort_Array'FIRST)
  1142.                  ) and
  1143.                  (I /= Sort_Array'FIRST) then
  1144.                 J := Index_Type'VAL (
  1145.                        (Index_Type'POS (I) + Index_Type'POS (Sort_Array'FIRST) - 2)
  1146.                        / 2);
  1147.            else
  1148.              exit;  -- Exit while loop.
  1149.           end if;
  1150.         end loop;  -- End of while loop.
  1151.  
  1152.         Update_Performance_Instrumentation (Local_Comparisons);
  1153.  
  1154.         if not Equal (Temporary_Component,Sort_Array (I)) then
  1155.           Update_Performance_Instrumentation (Local_Exchanges);
  1156.           Sort_Array (I) := Temporary_Component;
  1157.         end if;
  1158.       end loop;  -- End of for loop.
  1159.  
  1160.       -- We remove Sort_Array (Sort_Array'FIRST) and place it in its
  1161.       -- proper position in the array. We then adjust the heap.
  1162.  
  1163.       for K in reverse Index_Type'SUCC (Sort_Array'FIRST) .. Sort_Array'LAST loop
  1164.         Update_Performance_Instrumentation (Local_Exchanges);
  1165.         Temporary_Component := Sort_Array (K);
  1166.         Sort_Array (K) := Sort_Array (Sort_Array'FIRST);
  1167.  
  1168.         -- Readjust the heap of order K-1. Move Temporary_Component down the
  1169.         -- heap for proper position.
  1170.  
  1171.         I := Sort_Array'FIRST;
  1172.         J := Index_Type'SUCC (I);
  1173.  
  1174.         -- The following if statement can be described as follows:
  1175.         --   if (Sort_Array (Element#2) < Sort_Array (Element#3)) and
  1176.         --      (Position of K's predecessor >= Position of Element#3) then
  1177.         --     J := Position of Element#3;
  1178.         --   end if;
  1179.         -- The complications are due to the generic nature of the
  1180.         -- algorithm.
  1181.  
  1182.         Update_Performance_Instrumentation (Local_Comparisons);
  1183.  
  1184.         if ((Sort_Array (Index_Type'SUCC (Sort_Array'FIRST))) <
  1185.             (Sort_Array (Index_Type'SUCC (Index_Type'SUCC (Sort_Array'FIRST))))
  1186.            ) and
  1187.            (Index_Type'PRED (K) >=
  1188.             Index_Type'SUCC (Index_Type'SUCC (Sort_Array'FIRST))
  1189.            ) then
  1190.           J := Index_Type'SUCC (Index_Type'SUCC (Sort_Array'FIRST));
  1191.         end if;
  1192.  
  1193.         -- J is the larger son of I in the heap of size K-1.
  1194.  
  1195.         while J <= Index_Type'PRED (K) loop
  1196.           Update_Performance_Instrumentation (Local_Comparisons);
  1197.  
  1198.           if (Sort_Array (J) < Temporary_Component) or
  1199.              Equal (Sort_Array (J),Temporary_Component) then
  1200.             exit;  -- exit while loop
  1201.           end if;
  1202.  
  1203.           Update_Performance_Instrumentation (Local_Exchanges);
  1204.           Sort_Array (I) := Sort_Array (J);
  1205.           I := J;
  1206.  
  1207.           if (((Index_Type'POS (I) * 2) - Index_Type'POS (Sort_Array'FIRST) + 1) <=
  1208.               Index_Type'POS (Index_Type'PRED (Sort_Array'LAST))
  1209.              ) and
  1210.              (((Index_Type'POS (I) * 2) - Index_Type'POS (Sort_Array'FIRST) + 1) >=
  1211.               Index_Type'POS (Sort_Array'FIRST)
  1212.              ) then
  1213.             J := Index_Type'VAL (
  1214.                    (Index_Type'POS (I) * 2) - Index_Type'POS (Sort_Array'FIRST) + 1);
  1215.           else
  1216.             exit;  -- Exit while loop.
  1217.           end if;
  1218.  
  1219.           if Index_Type'SUCC (J) <= Index_Type'PRED (K) then
  1220.             Update_Performance_Instrumentation (Local_Comparisons);
  1221.  
  1222.             if Sort_Array (J) < Sort_Array (Index_Type'SUCC (J)) then
  1223.               J := Index_Type'SUCC (J);
  1224.             end if;
  1225.           end if;
  1226.         end loop;  -- End of while loop.
  1227.  
  1228.         Update_Performance_Instrumentation (Local_Exchanges);
  1229.         Sort_Array (I) := Temporary_Component;
  1230.       end loop;  -- End of for loop.
  1231.     end if;
  1232.  
  1233.     Number_of_Comparisons := Local_Comparisons;
  1234.     Number_of_Exchanges   := Local_Exchanges;
  1235.   end Heapsort;
  1236.  
  1237.   -- Simple insertion sort follows below. It is O(N**2), but usually
  1238.   -- better than a bubble sort.
  1239.  
  1240.   procedure Insertion_Sort (
  1241.     Sort_Array             : in out Array_Type;
  1242.     Number_of_Comparisons,
  1243.     Number_of_Exchanges    :    out Performance_Instrumentation_Type) is
  1244.  
  1245.     Local_Comparisons,
  1246.     Local_Exchanges     : Performance_Instrumentation_Type := 0;
  1247.     I                   : Index_Type;
  1248.     Temporary_Component : Component_Type;
  1249.     Found               : BOOLEAN;
  1250.   begin
  1251.     -- Handle special cases of singleton/null arrays...
  1252.     -- do nothing.
  1253.  
  1254.     if Sort_Array'FIRST < Sort_Array'LAST then
  1255.       -- Initially Sort_Array (Sort_Array'FIRST) may be thought of
  1256.       -- as a sorted file of one element. After each repetition of
  1257.       -- the following loop, the elements Sort_Array (Sort_Array'FIRST)
  1258.       -- through Sort_Array (K) are in order.
  1259.  
  1260.       for K in Index_Type'SUCC (Sort_Array'FIRST) .. Sort_Array'LAST loop
  1261.         -- insert Sort_Array (K) into the sorted file
  1262.  
  1263.         Temporary_Component := Sort_Array (K);
  1264.  
  1265.         -- Move down one position all elements "greater" than
  1266.         -- Temporary_Component
  1267.  
  1268.         I := Index_Type'PRED (K);
  1269.         Found := FALSE;
  1270.  
  1271.         while (not Found) loop
  1272.           Update_Performance_Instrumentation (Local_Comparisons);
  1273.  
  1274.           if Temporary_Component < Sort_Array (I) then
  1275.             Update_Performance_Instrumentation (Local_Exchanges);
  1276.             Sort_Array (Index_Type'SUCC (I)) := Sort_Array (I);
  1277.  
  1278.             if I /= Sort_Array'FIRST then
  1279.               I := Index_Type'PRED (I);
  1280.             else
  1281.               exit;  -- Exit while loop.
  1282.             end if;
  1283.           else
  1284.             Found := TRUE;
  1285.           end if;
  1286.         end loop;  -- End of while loop.
  1287.  
  1288.         -- Insert Temporary_Component at proper position.
  1289.  
  1290.         Update_Performance_Instrumentation (Local_Exchanges);
  1291.  
  1292.         if Found then
  1293.           Sort_Array (Index_Type'SUCC (I)) := Temporary_Component;
  1294.         else
  1295.           Sort_Array (Sort_Array'FIRST) := Temporary_Component;
  1296.         end if;
  1297.       end loop;  -- End of for loop.
  1298.     end if;
  1299.  
  1300.     Number_of_Comparisons := Local_Comparisons;
  1301.     Number_of_Exchanges := Local_Exchanges;
  1302.   end Insertion_Sort;
  1303.  
  1304.   -- The straight merge sort procedure below is O(NlogN) and is instable.
  1305.  
  1306.   procedure Merge_Sort (
  1307.     Sort_Array             : in out Array_Type;
  1308.     Number_of_Comparisons,
  1309.     Number_of_Exchanges    :    out Performance_Instrumentation_Type) is
  1310.  
  1311.     Auxiliary_Array    : Array_Type (Sort_Array'FIRST .. Sort_Array'LAST);
  1312.     Lower_Bound1,
  1313.     Lower_Bound2,
  1314.     Upper_Bound1,
  1315.     Upper_Bound2,
  1316.     Auxiliary_Index,
  1317.     I, J               : Index_Type;
  1318.     I_Overflow,
  1319.     J_Overflow,
  1320.     Aux_Overflow       : BOOLEAN;
  1321.     Size               : POSITIVE := 1;  -- Merge files of size 1.
  1322.     Local_Comparisons,
  1323.     Local_Exchanges    : Performance_Instrumentation_Type := 0;
  1324.   begin
  1325.     while Size < Sort_Array'LENGTH loop
  1326.       Lower_Bound1 := Sort_Array'FIRST;
  1327.       Auxiliary_Index := Auxiliary_Array'FIRST;
  1328.  
  1329.       -- Check if there are two files to merge.
  1330.  
  1331.       while (Index_Type'POS (Lower_Bound1) + Size) <=
  1332.              Index_Type'POS (Sort_Array'LAST) loop
  1333.         I_Overflow := FALSE;
  1334.         J_Overflow := FALSE;
  1335.         Aux_Overflow := FALSE;
  1336.  
  1337.         -- Compute remaining indices.
  1338.  
  1339.         Lower_Bound2 := Index_Type'VAL (Index_Type'POS (Lower_Bound1) +
  1340.                                         Size);
  1341.         Upper_Bound1 := Index_Type'PRED (Lower_Bound2);
  1342.  
  1343.         if Index_Type'POS (Lower_Bound2) + Size - 1 >
  1344.            Index_Type'POS (Sort_Array'LAST) then
  1345.           Upper_Bound2 := Sort_Array'LAST;
  1346.         else
  1347.           Upper_Bound2 := Index_Type'VAL (Index_Type'POS (Lower_Bound2) +
  1348.                                           Size - 1);
  1349.         end if;
  1350.  
  1351.         -- Proceed through the two subfiles.
  1352.  
  1353.         I := Lower_Bound1;
  1354.         J := Lower_Bound2;
  1355.  
  1356.         while (I <= Upper_Bound1) and (J <= Upper_Bound2) loop
  1357.           -- Enter smaller into Auxiliary_Array.
  1358.  
  1359.           Update_Performance_Instrumentation (Local_Comparisons);
  1360.           Update_Performance_Instrumentation (Local_Exchanges);
  1361.  
  1362.           if (Sort_Array (I) < Sort_Array (J)) or
  1363.              Equal (Sort_Array (I),Sort_Array (J)) then
  1364.             Auxiliary_Array (Auxiliary_Index) := Sort_Array (I);
  1365.  
  1366.             if Auxiliary_Index /= Auxiliary_Array'LAST then
  1367.               Auxiliary_Index := Index_Type'SUCC (Auxiliary_Index);
  1368.             else
  1369.               Aux_Overflow := TRUE;
  1370.             end if;
  1371.  
  1372.             if I /= Sort_Array'LAST then
  1373.               I := Index_Type'SUCC (I);
  1374.             else
  1375.               I_Overflow := TRUE;
  1376.               exit;
  1377.             end if;
  1378.           else
  1379.             Auxiliary_Array (Auxiliary_Index) := Sort_Array (J);
  1380.  
  1381.             if Auxiliary_Index /= Auxiliary_Array'LAST then
  1382.               Auxiliary_Index := Index_Type'SUCC (Auxiliary_Index);
  1383.             else
  1384.               Aux_Overflow := TRUE;
  1385.             end if;
  1386.  
  1387.             if J /= Sort_Array'LAST then
  1388.               J := Index_Type'SUCC (J);
  1389.             else
  1390.               J_Overflow := TRUE;
  1391.               exit;
  1392.             end if;
  1393.           end if;
  1394.         end loop;  -- While loop.
  1395.  
  1396.         -- At this point one of the subfiles has been exhausted.
  1397.         -- Insert any remaining portions of the other file.
  1398.  
  1399.         while (not I_Overflow) and (I <= Upper_Bound1) loop
  1400.           Update_Performance_Instrumentation (Local_Exchanges);
  1401.  
  1402.           Auxiliary_Array (Auxiliary_Index) := Sort_Array (I);
  1403.  
  1404.           if I /= Sort_Array'LAST then
  1405.             I := Index_Type'SUCC (I);
  1406.           else
  1407.             I_Overflow := TRUE;
  1408.           end if;
  1409.  
  1410.           if Auxiliary_Index /= Auxiliary_Array'LAST then
  1411.             Auxiliary_Index := Index_Type'SUCC (Auxiliary_Index);
  1412.           else
  1413.             Aux_Overflow := TRUE;
  1414.           end if;
  1415.         end loop;
  1416.  
  1417.         while (not J_Overflow) and (J <= Upper_Bound2) loop
  1418.           Update_Performance_Instrumentation (Local_Exchanges);
  1419.  
  1420.           Auxiliary_Array (Auxiliary_Index) := Sort_Array (J);
  1421.  
  1422.           if J /= Sort_Array'LAST then
  1423.             J := Index_Type'SUCC (J);
  1424.           else
  1425.             J_Overflow := TRUE;
  1426.           end if;
  1427.  
  1428.           if Auxiliary_Index /= Auxiliary_Array'LAST then
  1429.             Auxiliary_Index := Index_Type'SUCC (Auxiliary_Index);
  1430.           else
  1431.             Aux_Overflow := TRUE;
  1432.           end if;
  1433.         end loop;
  1434.  
  1435.         -- Advance Lower_Bound1 to start of next pair of files.
  1436.  
  1437.         if Index_Type'POS (Upper_Bound2) + 1 <=
  1438.            Index_Type'POS (Sort_Array'LAST) then
  1439.           Lower_Bound1 := Index_Type'SUCC (Upper_Bound2);
  1440.         else
  1441.           Lower_Bound1 := Sort_Array'LAST;
  1442.         end if;
  1443.       end loop;  -- While loop.
  1444.  
  1445.       -- Copy any remaining single file.
  1446.  
  1447.       I := Lower_Bound1;
  1448.  
  1449.       while not Aux_Overflow loop
  1450.         Update_Performance_Instrumentation (Local_Exchanges);
  1451.  
  1452.         Auxiliary_Array (Auxiliary_Index) := Sort_Array (I);
  1453.  
  1454.         if Auxiliary_Index /= Auxiliary_Array'LAST then
  1455.           Auxiliary_Index := Index_Type'SUCC (Auxiliary_Index);
  1456.         else
  1457.           Aux_Overflow := TRUE;
  1458.         end if;
  1459.  
  1460.         if I /= Sort_Array'LAST then
  1461.           I := Index_Type'SUCC (I);
  1462.         else
  1463.           I_Overflow := TRUE;
  1464.         end if;
  1465.       end loop;
  1466.  
  1467.       -- Adjust Sort_Array and Size.
  1468.  
  1469.       Sort_Array := Auxiliary_Array;
  1470.  
  1471.       Size := Size * 2;
  1472.     end loop;  -- While loop.
  1473.  
  1474.     Number_of_Comparisons := Local_Comparisons;
  1475.     Number_of_Exchanges := Local_Exchanges;
  1476.   end Merge_Sort;
  1477.  
  1478.   procedure Sort (
  1479.     Sort_Array             : in out Array_Type;
  1480.     Number_of_Comparisons,
  1481.     Number_of_Exchanges    :    out Performance_Instrumentation_Type;
  1482.     Sort_Algorithm         : in     Sort_Algorithm_Type := Quicksort) is
  1483.   begin
  1484.     -- Call the right sorting algorithm.
  1485.  
  1486.     case Sort_Algorithm is
  1487.       when Quicksort =>
  1488.         Quicksort (Sort_Array,Number_of_Comparisons,Number_of_Exchanges);
  1489.       when Recursive_Quicksort =>
  1490.         Recursive_Quicksort (Sort_Array,Number_of_Comparisons,Number_of_Exchanges);
  1491.       when Bsort =>
  1492.         Bsort (Sort_Array,Number_of_Comparisons,Number_of_Exchanges);
  1493.       when Bubble_Sort =>
  1494.         Bubble_Sort (Sort_Array,Number_of_Comparisons,Number_of_Exchanges);
  1495.       when Bubble_Sort_with_Quick_Exit =>
  1496.         Bubble_Sort_with_Quick_Exit (Sort_Array,Number_of_Comparisons,Number_of_Exchanges);
  1497.       when Selection_Sort =>
  1498.         Selection_Sort (Sort_Array,Number_of_Comparisons,Number_of_Exchanges);
  1499.       when Heapsort =>
  1500.         Heapsort (Sort_Array,Number_of_Comparisons,Number_of_Exchanges);
  1501.       when Insertion_Sort =>
  1502.         Insertion_Sort (Sort_Array,Number_of_Comparisons,Number_of_Exchanges);
  1503.       when Merge_Sort =>
  1504.         Merge_Sort (Sort_Array,Number_of_Comparisons,Number_of_Exchanges);
  1505.     end case;
  1506.   end Sort;
  1507.  
  1508.   -- Overloading of procedure Sort that does not return instrumentation
  1509.   -- analysis data follows below.
  1510.  
  1511.   procedure Sort (
  1512.     Sort_Array     : in out Array_Type;
  1513.     Sort_Algorithm : in     Sort_Algorithm_Type := Quicksort) is
  1514.  
  1515.     Dummy_Comparisons,
  1516.     Dummy_Exchanges    : Performance_Instrumentation_Type;
  1517.   begin
  1518.     Sort (Sort_Array,Dummy_Comparisons,Dummy_Exchanges,Sort_Algorithm);
  1519.   end Sort;
  1520.  
  1521.   -- Overloading of procedure Sort used to preserve original data and to
  1522.   -- return instrumentation analysis results follows below.
  1523.  
  1524.   procedure Sort (
  1525.     Unsorted_Array         : in     Array_Type;
  1526.     Sorted_Array           :    out Array_Type;
  1527.     Number_of_Comparisons,
  1528.     Number_of_Exchanges    :    out Performance_Instrumentation_Type;
  1529.     Sort_Algorithm         : in     Sort_Algorithm_Type := Quicksort) is
  1530.  
  1531.     Local_Array : Array_Type (Unsorted_Array'RANGE) := Unsorted_Array;
  1532.   begin
  1533.     Number_of_Comparisons := 0;
  1534.     Number_of_Exchanges   := 0;
  1535.  
  1536.     -- Check for equal length of both arrays.
  1537.  
  1538.     if Unsorted_Array'LENGTH /= Sorted_Array'LENGTH then
  1539.       raise Sort_Arrays_Length_Mismatch;
  1540.     end if;
  1541.  
  1542.     Sort (Local_Array,Number_of_Comparisons,Number_of_Exchanges,
  1543.       Sort_Algorithm);
  1544.  
  1545.     Sorted_Array := Local_Array;
  1546.   end Sort;
  1547.  
  1548.   -- Overloading of procedure Sort used to preserve the original data
  1549.   -- follows below.
  1550.  
  1551.   procedure Sort (
  1552.     Unsorted_Array : in     Array_Type;
  1553.     Sorted_Array   :    out Array_Type;
  1554.     Sort_Algorithm : in     Sort_Algorithm_Type := Quicksort) is
  1555.  
  1556.     Local_Array        : Array_Type (Unsorted_Array'RANGE) := Unsorted_Array;
  1557.     Dummy_Comparisons,
  1558.     Dummy_Exchanges    : Performance_Instrumentation_Type;
  1559.   begin
  1560.     -- Check for equal length of both arrays.
  1561.  
  1562.     if Unsorted_Array'LENGTH /= Sorted_Array'LENGTH then
  1563.       raise Sort_Arrays_Length_Mismatch;
  1564.     end if;
  1565.  
  1566.     Sort (Local_Array,Dummy_Comparisons,Dummy_Exchanges,Sort_Algorithm);
  1567.  
  1568.     Sorted_Array := Local_Array;
  1569.   end Sort;
  1570.  
  1571.   -- Overloading of function Sort used in inline expressions follows below.
  1572.  
  1573.   function Sort (
  1574.     Sort_Array     : in Array_Type;
  1575.     Sort_Algorithm : in Sort_Algorithm_Type := Quicksort)
  1576.     return Array_Type is
  1577.  
  1578.     Sorted_Array       : Array_Type (Sort_Array'RANGE) := Sort_Array;
  1579.     Dummy_Comparisons,
  1580.     Dummy_Exchanges    : Performance_Instrumentation_Type;
  1581.   begin
  1582.     Sort (Sorted_Array,Dummy_Comparisons,Dummy_Exchanges,Sort_Algorithm);
  1583.     
  1584.     return Sorted_Array;
  1585.   end Sort;
  1586. end Sort_Utilities;
  1587.